from django.http import response,HttpResponseNotAllowed
from django.test import TestCase

# Create your tests here.
# class ViewTest(TestCase):  # 测试类  注意：测试类必须继承TestCase类，否则会报错。
#     a = 10
    
#     def test_1(self):
#         print("test_1",self.a)
        
# ViewTest().test_1()  # 测试函数
#------------------------------------------------------------------------------

class View:
    http_method_names = [
        "get",
        "post",
        "put",
        "patch",
        "delete",
        "head",
        "options",
        "trace",
    ]
    
    @classmethod
    def as_view(cls, **initkwargs):
        """
        模拟django的as_view()方法，返回一个函数。
        """
        # 1.参数检查
        for key in initkwargs:
            if key in cls.http_method_names:  # 如果参数中包含http方法名，则抛出异常。
                raise TypeError(f"不能使用HTTP方法名称{key}作为参数")
        
        # 2.返回一个函数。
        def view(request, *args, **kwargs):  # 这里的view函数是一个闭包函数，它会保留initkwargs中的参数。
            # 2.1创建一个类的实例
            self = cls(**initkwargs) 
            
            # 初始化请求属性
            self.request = request  # 注意：这里的request是一个对象，不是一个字符串。
            self.args = args  # 注意：这里的args是一个元组，不是一个字符串。
            self.kwargs = kwargs  # 注意：这里的kwargs是一个字典，不是一个字符串。
            # 2.2调用dispatch方法，分发请求
            if request.method.lower() in self.http_method_names:  # 如果请求方法在http_method_names中，则调用对应的方法。
                
                handler = getattr(self, request.method.lower(),None)  # 获取请求方法对应的方法。
                if handler:
                    return handler(request, *args, **kwargs)  # 调用方法，返回响应。
                # 2.3如果请求方法不在http_method_names中，则返回405错误。
                # return HttpResponseNotAllowed(cls.http_method_names)  # 返回405错误。
        return view  
      

# 使用示例：
class MyView(View):  # 定义一个类，继承View类。
    see = "hello"
    def __init__(self,**initkwargs):
        for key,value in initkwargs.items():  # 遍历initkwargs中的参数。
            setattr(self,key,value)  # 设置实例属性。
            
    def get(self, request):  # 定义一个get方法。
        return f"{self.see} GET请求" 

    def post(self, request):  # 定义一个post方法。
        return f"{self.see} POST请求" 
            
# 模拟路由配置，将请求分发到对应的方法。
url_patterns ={
    '/test':MyView.as_view(see="你好"),  # 注意：这里的as_view()方法是一个闭包函数，它会保留initkwargs中的参数。
} 

# 模拟请求
def handler_request(path,method="get"):
    view = url_patterns.get(path) 
    if view:  # 如果找到了对应的视图函数，则调用它。
        class Request:
            def __init__(self,method):
                self.method = method  # 请求方法。
        return view(Request(method))  # 调用视图函数，返回响应。
    return "404 Not Found"  # 如果没有找到对应的视图函数，则返回404错误。

# print(handler_request('/test',"GET"))           
# print(handler_request('/test',"POST"))    
       
class Counter:  # 定义一个计数器类。
    
    def __init__(self):
        self.count = 0
    # __call__方法，可以让一个类的实例像函数一样被调用。
    def __call__(self):  # *args和**kwargs是可变参数，它们可以接收任意数量的参数。
        self.count += 1  # 每次调用时，计数器加1。
        return self.count  # 返回计数器的值。
# 创建一个实例：
counter = Counter()  # 创建一个计数器的实例。
# 普通类调用，会直接返回类的本身
print(counter)   # <__main__.Counter object at 0x00000144585DDA90>  这里的counter是一个实例，不是一个类。
print(counter())  # 调用计数器实例，返回计数器的值。1
print(counter())  # 调用计数器实例，返回计数器的值。2
print(counter())  # 调用计数器实例，返回计数器的值。3
